import { useUserStore } from '/@/store/modules/user'
import {
  contentType,
  debounce,
  messageName,
  timeout,
  statusName,
  successCode,
} from '/@/config'
import qs from 'qs'
import router from '/@/router'
import { isArray } from '/@/utils/validate'
import { addErrorLog, needErrorLog } from '/@vab/plugins/errorLog'
import { refreshToken } from '/@/api/refreshToken'
import { gp } from '/@vab/plugins/vab'
import { ElMessage } from 'element-plus'
import { removeToken } from './token'

let loadingInstance: any

let refreshToking = false

let requests: any[] = []

// 操作正常Code数组
const codeVerificationArray = isArray(successCode)
  ? [...successCode]
  : [...[successCode]]

const CODE_MESSAGE: any = {
  0: '请求错误',
  200: '成功',
  201: '创建成功',
  202: '请求成功',
  204: '请求成功',
  302: '无权限, 请联系管理员添加权限',
  303: '账户名或密码错误，请重新输入。',
  304: '功能接口无权限，请联系管理员',
  305: '无权限, 请联系管理员添加权限',
  400: '请求错误',
  401: '请登录',
  402: '令牌过期',
  403: '用户得到授权，但是访问是被禁止的',
  404: '接口不存在',
  405: '请求体内的类型错误',
  406: '请求格式不可得',
  410: '请求资源已过期',
  422: '验证失败',
  429: '请求频繁, 请稍后再试',
  430: 'RPC调用失败',
  431: '服务器正忙, 请稍后重试 :)',
  432: '服务节点不存在',
  500: '服务端异常',
  501: 'RSA 缺少 header',
  502: 'RSA 解密失败',
  503: '服务不可用，服务器暂时过载或维护',
  504: '网关超时',
  601: '请检查你的表单数据',
}

/**
 * axios请求拦截器配置
 * @param config
 * @returns {any}
 */
const requestConf = (config: any) => {
  const userStore = useUserStore()
  const { token } = userStore

  // 不规范写法 可根据setting.config.js tokenName配置随意自定义headers
  if (token) config.headers['Authorization'] = token

  if (
    config.data &&
    config.headers['Content-Type'] ===
      'application/x-www-form-urlencoded;charset=UTF-8'
  )
    config.data = qs.stringify(config.data)
  if (debounce.some((item: string) => config.url.includes(item)))
    loadingInstance = gp.$baseLoading()
  return config
}

/**
 * 刷新刷新令牌
 * @param config 过期请求配置
 * @returns {any} 返回结果
 */
const tryRefreshToken = async (config: any) => {
  if (!refreshToking) {
    refreshToking = true
    try {
      const {
        data: { token },
      } = await refreshToken()
      if (token) {
        const { setToken } = useUserStore()
        setToken(token)
        // 已经刷新了token，将所有队列中的请求进行重试
        requests.forEach((cb) => cb(token))
        requests = []
        return instance(requestConf(config))
      }
    } catch (error) {
      console.error('refreshToken error =>', error)
      router.push({ path: '/login', replace: true }).then(() => {})
    } finally {
      refreshToking = false
    }
  } else {
    return new Promise((resolve) => {
      // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
      requests.push(() => {
        resolve(instance(requestConf(config)))
      })
    })
  }
}

// 刷新浏览器
const reload = ()=>{
  setTimeout(() => { location.reload() }, 1000);
}

/**
 * axios响应拦截器
 * @param config {any} 请求配置
 * @param data {any} response数据
 * @param status {any} HTTP status
 * @param statusText {any} HTTP status text
 * @returns {Promise<*|*>}
 */
const handleData = async ({
  config,
  data,
  status,
  statusText,
}: {
  config: any
  data: any
  status: any
  statusText: any
}) => {
  const { resetAll } = useUserStore()
  if (loadingInstance) loadingInstance.close()
  // 若data.code存在，覆盖默认code
  let code = data && data[statusName] ? data[statusName] : status
  // 若code属于操作正常code，则status修改为200
  if (codeVerificationArray.indexOf(data[statusName]) + 1) code = 200

  switch (code) {
    case 200:
      return data
    case 302:
      await resetAll()
      // reload()
      break
    case 303:
      await resetAll()
      // reload()
      break
    case 305:
      await resetAll()
      // reload()
      break
    case 401:
      await resetAll()
      break
    case 402:
      return await tryRefreshToken(config)
    case 403:
      router.push({ path: '/403' }).then(() => {})
      break

    default:
  }
  // 异常处理
  // 若data.msg存在，覆盖默认提醒消息
  const errMsg = `${
    data && data[messageName]
      ? data[messageName]
      : CODE_MESSAGE[code]
      ? CODE_MESSAGE[code]
      : data.message
  }`

  // 是否显示高亮错误(与errorHandler钩子触发逻辑一致)
  gp.$baseMessage(errMsg, 'error', 'hey')
  if (needErrorLog())
    addErrorLog({ message: errMsg, stack: data, isRequest: true })
  return Promise.reject(data)
}
/**
 * @description axios初始化
 */
const instance = axios.create({
  baseURL: `${import.meta.env.VITE_APP_BASE_URL}`,
  timeout,
  headers: {
    'Content-Type': contentType,
  },
  method: 'POST',
  withCredentials: true,
})

/**
 * @description axios请求拦截器
 */
instance.interceptors.request.use(requestConf, (error) => {
  return Promise.reject(error)
})

/**
 * @description axios响应拦截器
 */
instance.interceptors.response.use(
  (response) => handleData(response),
  // @ts-ignore
  // async (response:any) => {
  //   if (response.data.code != 200) {
  //     ElMessage.error(response.data.message)
  //     return Promise.reject(response)
  //   }
  //   return Promise.resolve(response.data)
  // },
  (error) => {
    console.log(error, 'error');

    // const { response } = error
    // if (response === undefined) {
    //   if (loadingInstance) loadingInstance.close()
    //   gp.$baseMessage(
    //     '连接后台接口失败，可能由以下原因造成：后端不支持跨域CORS、接口地址不存在、请求超时等，请联系管理员排查后端接口问题 ',
    //     'error',
    //     'hey'
    //   )
    //   return {}
    // } else return handleData(response)
  }
)

export default instance
